#
# L1 - Level 1
#
# This is the code that communicates to the server. It passes incomming information
#  over to the world model, populating it for all to work with. It also takes basic
#  commands from CI into a queue and sends them to the server.
#

from threading import Thread

from robosock import sockwrap
from sexp import *

# function that does nothing
def nop(*x): pass

class player(Thread):
	def __init__(self, simpleWorld=None, eqCallback=nop, team="rukota", goalie=False, host="localhost", port=6000):
		Thread.__init__(self)
		
		# set up other vars
		self.world = simpleWorld
		self.queue = []
		
		# function to be called when queue is empty
		self.eqCallback = eqCallback
		
		self.exit = False # thread runs untill this is set to true
		
		self.socket = sockwrap(host)
		
		if goalie: self.socket.send("(init "+team+" (version 9.0) (goalie))")
		else: self.socket.send("(init "+team+" (version 9.0))")
		
		res = self.socket.grab()
		
		if res is None:
		    print "No response from server '" + host +":"+str(port)+"'."
		    return None
		else: print "Connected to server %s:%i on local port %i..." % (host, port, res[1][1])
		
		# set up init info
		self.socket.serv_port = res[1][1]
		
		# init world, check for errors
		if self.world: 
			if not self.world.init(res, team): 
				self.exit = True
				self.socket.close()
				print "Disconnected from server. The end."
		else:
			print "Warning L1.player::__init__: L1 player created without an associated world. It is very lonely."
		
	def run(self):
		while not self.exit:
			msg = self.socket.grab()
			
			if msg is None:
				print "\nactiontimer: Lost connection to server..."
				break
			else: msg = msg[0]
			
			while saneSexp(msg):
				msg += self.socket.grab()
			message = getSexp(msg)
			
			# report to world what's going on
			if not self.world == None:
				self.world.report(message)
			
			# and take action!
			if(message[0] == 'sense_body'):
				self.send()
	
	def push(self, command, callback=nop, cb_args=[]):
		"Push an action to bottom of outgoing queue"
		self.queue[:0] = [[command, callback, cb_args]]
	
	def clear(self):
		"Empty actions out of outgoing queue"
		self.queue = []
        
	def send(self):
		"This function is run once a cycle, it sends commands to the server from the queue"
		if self.queue: # not empty?
			command, callback, cb_args = self.queue.pop()	# pop
			self.socket.send( printSexp(command) )			# send
			apply(callback, cb_args)						# call back
		else:
			self.eqCallback() # call back to populate queue
